package org.javaongems.client.vcl;

import org.javaongems.client.rt.lang.StringUtils;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.impl.FocusImpl;

public class ControlDomRenderer implements DomConstants {
	private static FocusImpl focusImpl = new FocusImpl();
	
	public Control control;
	public Element parentElement, element;	 

	public void setControl(Control ctrl) {
		control = ctrl;
	}

	public void sinkEvents(int eventBitsToAdd) {
		DOM.sinkEvents(element, eventBitsToAdd | DOM.getEventsSunk(element));
	}
	
	public void unsinkEvents(int eventBitsToRemove) {
		DOM.sinkEvents(element, DOM.getEventsSunk(element) & (~eventBitsToRemove));
	}
	
	public void setAccessKey(char key) {
		setAccessKey(element, key);
	}
	
	public void setFocus(boolean focus) {
		setFocus(element, focus);
	}
	
	public void setTabIndex(int idx) {
		setTabIndex(element, idx);
	}
	
	public void setParentElement(Element elm) {
		if (parentElement == elm && DOM.getParent(element) == parentElement)
			return;
		detachFromParent();
		parentElement = elm;
		attachToParent();
	}
	
	public boolean setElement(Element elm) {
		if (element == elm)
			return false;
		detachFromParent();
		parentElement = null;
		if (element != null)
			setGemsControl(null, element);
		element = elm;
		if (element != null) 
			setGemsControl(control, element);
		return true;
	}
	
	public void resetElement() {
		if (element == null)
			return;
		int count = DOM.getChildCount(element);
		for (int i = 0; i < count; i++) {
			Element child = DOM.getChild(element, 0);
			DOM.removeChild(element, child);
		}
	}
	
	native static public void setGemsControl(Control ctrl, Element elem) /*-{
    	elem.__gemsCtrl = ctrl;
	  }-*/;

	native static public Control getGemsControl(Element elem) /*-{
		if (elem.__gemsCtrl)
			return elem.__gemsCtrl;
		return null;
  	}-*/;

	public void detachFromParent() {
		if (parentElement != null) {
			Element naturalParent = DOM.getParent(element);
			if (naturalParent == parentElement)
				DOM.removeChild(parentElement, element);
		}
		if (element != null)
			DOM.setEventListener(element, null);
	}
	
	public void attachToParent() {
		if (parentElement != null) {
			DOM.appendChild(parentElement, element);
			if (element != null)
				DOM.setEventListener(element, control);
		}
	}
	
	public void refresh() {
		int curr = getElementIndexPosition();
		changeElementIndexPosition(curr);
	}
	
	public int getElementIndexPosition() {
		return DOM.getChildIndex(parentElement, element);
	}
	
	public void changeElementIndexPosition(int index) {
		DOM.removeChild(parentElement, element);
		DOM.insertChild(parentElement, element, index);
	}
	
	public boolean isVisible() {
		return isVisible(element);
	}

	public void setVisible(boolean vis) {
		if (control.isLoading()) return;
		setVisible(element, vis);
	}
	
	public boolean isEnabled() {
		return isEnabled(element);
	}
	
	public void setEnabled(boolean enabled) {
		if (control.isLoading()) return;
		setEnabled(element, enabled);
	}
	
	public void setFont(String f) {
		if (control.isLoading()) return;
		if (StringUtils.isEmpty(f)) {
			clearStyleFont(element);
		} else
			DOM.setStyleAttribute(element, STYLE_FONT, f);
	}
	
	public native void clearStyleFont(Element elem) /*-{
			elem.style.fontFamily = "";
			elem.style.fontSize = "";
			elem.style.fontStyle = "";
			elem.style.fontWeight = "";
			elem.style.fontVariant = "";
	}-*/;

	
	
	public void setTopPosition(int t) {
		if (control.isLoading()) return;
		setTopPosition(element, t);
	}
	
	public void setLeftPosition(int l) {
		if (control.isLoading()) return;
		setLeftPosition(element, l);
	}

	public void setBottomPosition(int b) {
		if (control.isLoading()) return;
		String val = "";
		if (b >= 0)
			val = b + "px";
		DOM.setStyleAttribute(element, STYLE_BOTTOM, val);
	}

	public void setStyleName(String style, boolean add) {
		setStyleName(element, style, add);
	}
	
	public void addStyleName(String style) {
		setStyleName(style, true);
	}
	
	public int getAbsoluteLeft() {
		return DOM.getAbsoluteLeft(element);
	}

	public int getAbsoluteTop() {
		return DOM.getAbsoluteTop(element);
	}

	public int getOffsetHeight() {
		return DOM.getIntAttribute(element, ATTR_OFFSET_HEIGHT);
	}

	public int getOffsetWidth() {
		return DOM.getIntAttribute(element, ATTR_OFFSET_WIDTH);
	}
	
	public String getStyleName() {
		return DOM.getAttribute(element, ATTR_CLASS_NAME);
	}

	public String getTitle() {
		return DOM.getAttribute(element, ATTR_TITLE);
	}

	public void removeStyleName(String style) {
		setStyleName(style, false);
	}
	
	public void setPixelSize(int width, int height) {
		if (control.isLoading()) return;
		setPixelSize(element, width, height);
	}

	public void setPixelWidth(int w) {
		if (control.isLoading()) return;
		setPixelWidth(element, w);
	}
	
	public void setPixelHeight(int h) {
		if (control.isLoading()) return;
		setPixelHeight(element, h);
	}
		
	static public String toDimensionValue(int v) {
		String val;
		if (v >= 0)
			val = v + "px";
		else if (v == Control.DIMENSION_100)
			val = DIM_100;
		else 
			val = DIM_AUTO;
		return val;
	}

	public void setStyleName(String style) {
		DOM.setAttribute(element, ATTR_CLASS_NAME, style);
	}

	public void setTitle(String title) {
		if (control.isLoading()) return;
		DOM.setAttribute(element, ATTR_TITLE, title);
	}
	
	public void setAutoSizing(boolean auto) {
		if (control.isLoading()) return;
		if (auto) {
			DOM.setStyleAttribute(element, STYLE_WIDTH, DIM_AUTO);
			DOM.setStyleAttribute(element, STYLE_HEIGHT, DIM_AUTO);
		} else {
			int w = DOM.getIntStyleAttribute(element, STYLE_WIDTH);
			int h = DOM.getIntStyleAttribute(element, STYLE_HEIGHT);
			control.setWidth(w);
			control.setHeight(h);
		}
	}
	
	public void setAlignment(int alignment) {
		if (control.isLoading()) return;
		setPositionStyle(POSITION_ABSOLUTE);
		setFloatStyle(FLOAT_NONE);
	}
	
	public void setPositionStyle(String style) {
		setPositionStyle(element, style);
	}
	
	public void setFloatStyle(String style) {
		setFloatStyle(element, style);
	}
	
	public void setTextAlignment(int alignment) {
		if (control.isLoading()) return;
		setTextAlignment(element, alignment);
	}
	
	public void setVerticalAlignment(String alignment) {
		if (control.isLoading()) return;
		setVerticalAlignment(element, alignment);
	}
	
	public void setBackgroundColor(String clr) {
		if (control.isLoading()) return;
		setBackgroundColor(element, clr);
	}
	
	public void setCaption() {
		if (control.isLoading()) return;
		String val = control.getCaption();
		setInnerText(element, val);
	}
	
	public void setCursor(String csr) {
		if (control.isLoading()) return;
		setCursor(element, csr);
	}
	
	public void setColor(String clr) {
		if (control.isLoading()) return;
		setColor(element, clr);
	}
	
	public void setText() {
		if (control.isLoading()) return;
		String val = control.getText();
		setInnerText(element, val);
	}
	
	public void setWordWrap(boolean wrap) {
		if (control.isLoading()) return;
		setWordWrap(element, wrap);
	}
	
	public String toString() {
	    if (element == null)
	      return "(null handle)";
	    return DOM.toString(element);
	}
	
	public void setBevel(boolean up) {
		setBevel(element, up);
	}
	
	public void setZindex(int i) {
		setZindex(element, i);
	}

	static public void setBevel(Element elm, boolean up) {
		String tl = up ? BORDER_BUTTON_HIGHLIGHT: BORDER_BUTTON_SHADOW;
		String br = up ? BORDER_BUTTON_SHADOW: BORDER_BUTTON_HIGHLIGHT;
		DOM.setStyleAttribute(elm, STYLE_BORDER_TOP, tl);
		DOM.setStyleAttribute(elm, STYLE_BORDER_LEFT, tl);
		DOM.setStyleAttribute(elm, STYLE_BORDER_BOTTOM, br);
		DOM.setStyleAttribute(elm, STYLE_BORDER_RIGHT, br);
	}
	
	static public void setBackgroundColor(Element elm, String clr) {
		DOM.setStyleAttribute(elm, STYLE_BACKGROUND_COLOR, clr);
	}
	
	static public void setBackgroundImage(Element elm, String imgUrl) {
		DOM.setStyleAttribute(elm, STYLE_BACKGROUND_IMAGE, "url('" + imgUrl + "')");
		DOM.setStyleAttribute(elm, STYLE_BACKGROUND_POSITION, "center center");
	}
	
	static public void setCursor(Element elm, String csr) {
		DOM.setStyleAttribute(elm, STYLE_CURSOR, csr);
	}
		
	static public void setColor(Element elm, String clr) {
		DOM.setStyleAttribute(elm, STYLE_COLOR, clr);
	}
	
	static public void setInnerText(Element elm, String txt) {
		if (txt == null)
			txt = StringUtils.EMPTY;
		DOM.setInnerHTML(elm, txt);
	}
		
	static public boolean isEnabled(Element elm) {
		return !DOM.getBooleanAttribute(elm, ATTR_DISABLED);
	}

	static public void setEnabled(Element elm, boolean enabled) {
		DOM.setBooleanAttribute(elm, ATTR_DISABLED, !enabled);
	}
	
	static public void setAccessKey(Element elm, char key) {
		DOM.setAttribute(elm, ATTR_ACCESSKEY, "" + key);
	}
			
	static public void setTabIndex(Element elm, int idx) {
		DOM.setAttribute(elm, ATTR_TABINDEX, "" + idx);
	} 
	
	static public void setFocus(Element elm, boolean focus) {
		if (focus)
			focusImpl.focus(elm);
		else
			focusImpl.blur(elm);
	}
	
	static public void setPositionStyle(Element elm, String style) {
		DOM.setStyleAttribute(elm, STYLE_POSITION, style);
	}
	
	static public void setFloatStyle(Element elm, String style) {
		DOM.setStyleAttribute(elm, STYLE_FLOAT, style);
	}
	
	static public void setPixelSize(Element elm, int width, int height) {
		setPixelWidth(elm, width);
		setPixelHeight(elm, height);
	}
	
	static public void setPixelHeight(Element elm, int h) {
		String val = toDimensionValue(h);
		DOM.setStyleAttribute(elm, STYLE_HEIGHT, val);
	}

	static public void setPixelWidth(Element elm, int w) {
		String val = toDimensionValue(w);
		DOM.setStyleAttribute(elm, STYLE_WIDTH, val);		
	}
	
	static public void setStyleName(Element elm, String style, boolean add) {
		String oldStyle = DOM.getAttribute(elm, ATTR_CLASS_NAME);
		if (oldStyle == null)
			oldStyle = "";
		int idx = oldStyle.indexOf(style);
		if (add) {
			if (idx == -1)
				DOM.setAttribute(elm, ATTR_CLASS_NAME, oldStyle + " " + style);
		} else {
			if (idx != -1) {
				String begin = oldStyle.substring(0, idx);
				String end = oldStyle.substring(idx + style.length());
				DOM.setAttribute(elm, ATTR_CLASS_NAME, begin + end);
			}
		}
	}
	
	static public void setTextAlignment(Element elm, int alignment) {
		String format = TEXT_LEFT;
		switch (alignment) {
		case Control.TEXT_ALIGNMENT_RIGHT: format = TEXT_RIGHT; break;
		case Control.TEXT_ALIGNMENT_CENTER: format = TEXT_CENTRE; break;
		case Control.TEXT_ALIGNMENT_JUSTIFY: format = TEXT_JUSTIFY; break;
		}
		DOM.setStyleAttribute(elm, STYLE_TEXT_ALIGN, format);
	}
	
	static public void setTopPosition(Element elm, int t) {
		DOM.setStyleAttribute(elm, STYLE_TOP, t + "px");
	}

	static public void setLeftPosition(Element elm, int l) {
		DOM.setStyleAttribute(elm, STYLE_LEFT, l + "px");
	}
	
	static public void setZindex(Element elm, int i) {
		DOM.setStyleAttribute(elm, STYLE_Z_INDEX, "" + i);
	}
	
	static public void setVerticalAlignment(Element elm, String alignment) {
		DOM.setStyleAttribute(elm, STYLE_VERTICAL_ALIGN, alignment);
	}
	
	public static native boolean isVisible(Element elem) /*-{
	    return (elem.style.display != 'none');
	}-*/;

	public static native void setVisible(Element elem, boolean visible) /*-{
	    elem.style.display = visible ? '' : 'none';
	}-*/;

	static public void setWordWrap(Element elm, boolean wrap) {
		String format = wrap ? TEXT_WRAP_NORMAL: TEXT_WRAP_NONE;
		DOM.setStyleAttribute(elm, STYLE_TEXT_WRAP, format);			
	}
	
	static public void setMargin(Element elm, int m) {
		String px = m + "px";
		DOM.setStyleAttribute(elm, STYLE_MARGIN, px);
	}
	
}